package com.google.gwt.gwtpages.client.applicationpresenter; import java.util.HashMap; import com.google.gwt.gwtpages.client.PageRequestSession; import com.google.gwt.gwtpages.client.Pages; import com.google.gwt.gwtpages.client.page.ApplicationPresenter; import com.google.gwt.gwtpages.client.page.LoadedPageContainer; import com.google.gwt.gwtpages.client.page.PageAttributes; import com.google.gwt.gwtpages.client.page.parameters.PageParameters; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.RootLayoutPanel; import com.google.gwt.user.client.ui.Widget; /** * Application presenter which can use several different application presenters * based on the page or session attributes. Each known presenter is mapped to a * String token and all available presenters are passed as entries into the * constructor. * * All nested application presenters *must* be layout panels as they will be * added to the {@link RootLayoutPanel} * * To change the presenter per page, you can either * <ul> * <li>add a {@link TokenProvider} to the {@link PageAttributes} in a page loader * using {@link PageAttributes#put(Class, Object)} with the Class parameter * being {@link CompositeLayoutApplicationPresenter.TokenProvider}</li> * <li>add a {@link TokenProvider} to the {@link PageRequestSession} in a page request * event using {@link PageAttributes#put(Class, Object)} with the Class * parameter being {@link CompositeLayoutApplicationPresenter.TokenProvider}</li> * </ul> * * If no Oracle is set, the default application presenter will be used. Note: * you also have the ability to directly set a page token (instead of an * implementation of the Oracle) by using the TOKEN_APPLICATION_PRESENTER key * with the value of the application presenter token String. * * @author Joe Hudson */ public class CompositeLayoutApplicationPresenter implements ApplicationPresenter { public static final Object PRESENTER_TOKEN_KEY = new Object(); protected HashMap<String, ApplicationPresenter> index = new HashMap<String, ApplicationPresenter>(); protected ApplicationPresenter currentPresenter; private String defaultToken; public CompositeLayoutApplicationPresenter(String defaultToken) { this.defaultToken = defaultToken; } /** * Register an application presenter with the provided token * * @param token * the token * @param applicationPresenter * {@link ApplicationPresenter} * @return this for chaining */ public CompositeLayoutApplicationPresenter register(String token, ApplicationPresenter applicationPresenter) { index.put(token, applicationPresenter); return this; } public void init(Pages settings) { for (ApplicationPresenter presenter : index.values()) presenter.init(settings); } public void showPage(LoadedPageContainer page, PageParameters parameters, PageRequestSession session) { TokenProvider oracle = session.get(TokenProvider.class, true); ApplicationPresenter presenter = null; String presenterToken = null; if (null == oracle) { presenterToken = (String) session.get(PRESENTER_TOKEN_KEY, true); if (null == presenterToken) { presenterToken = defaultToken; } } else { presenterToken = oracle .getPresenterToken(page, parameters, session); } if (null != presenterToken) presenter = index.get(presenterToken); if (null == presenter) { if (null == presenterToken) throw new NullPointerException( "Null presenter token for page '" + page.getPageToken() + "'"); else throw new NullPointerException( "No presenter located for token '" + presenterToken + "'"); } if (null == currentPresenter || !currentPresenter.equals(presenter)) { if (null != currentPresenter) RootLayoutPanel.get().clear(); RootLayoutPanel.get().add((Widget) presenter.asWidget()); currentPresenter = presenter; } try { presenter.showPage(page, parameters, session); } catch (Throwable t) { currentPresenter.clearCurrentPage(); currentPresenter = null; clearCurrentPage(); if (t instanceof RuntimeException) throw (RuntimeException) t; else throw new RuntimeException(t); } } public void clearCurrentPage() { RootLayoutPanel.get().clear(); } public Widget asWidget() { return null; } public interface TokenProvider { public String getPresenterToken(LoadedPageContainer page, PageParameters parameters, PageRequestSession session); } }